package com.itzxx.huazhun.ui.collection.readall

import android.text.TextUtils
import cn.com.heaton.blelibrary.ble.model.BleDevice
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import com.itzxx.huazhun.data.dao.CollectionEntity
import com.itzxx.huazhun.data.dao.DbHelper
import com.itzxx.huazhun.data.dao.ProbeRecordEntity
import com.itzxx.huazhun.data.model.EventMessage
import com.itzxx.huazhun.data.model.EventType
import com.itzxx.huazhun.data.model.ProbeAllInfo
import com.itzxx.huazhun.data.model.ProbeInfo
import com.itzxx.huazhun.data.model.ProbeTestingInfo
import com.itzxx.huazhun.data.repository.HttpRequestCoroutine
import com.itzxx.huazhun.utils.ExcelUtil
import com.itzxx.huazhun.utils.UserCacheHelper
import com.itzxx.huazhun.utils.ble.BleConstant
import com.itzxx.huazhun.utils.ble.BleHelper
import com.itzxx.huazhun.utils.ble.BleListener
import com.itzxx.huazhun.utils.ble.BleRequestData
import com.itzxx.huazhun.utils.ble.BleWriteListener
import com.itzxx.library_base_ktx.base.viewmodel.BaseViewModel
import com.itzxx.library_base_ktx.callback.databind.BooleanObservableField
import com.itzxx.library_base_ktx.callback.livedata.event.EventLiveData
import com.itzxx.library_base_ktx.ext.request
import com.itzxx.library_base_ktx.ext.util.loge
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import org.greenrobot.eventbus.EventBus
import org.json.JSONObject
import java.math.BigDecimal
import java.math.RoundingMode


class ReadCollectionAllDataViewModel : BaseViewModel() {

    private var checkBleDevice: BleDevice? = null
    private var mBleListener: BleListener? = null

    val readCollectionBtn = BooleanObservableField(false)

    val probeInfoObservableField = EventLiveData<ProbeInfo>()

    //准备获取全部信息的队列
    val queueProbeAllInfo = ArrayDeque<ProbeAllInfo>()

    //上传数据队列
    val queueCollectionEntity = ArrayDeque<CollectionEntity>()

    //读取完成数据
    val readProbeAllInfoEndList = mutableListOf<ProbeAllInfo>()

    //当前正在采集的
    lateinit var currentTestingProbeAllInfo: ProbeAllInfo

    //单个探头基础数据
    lateinit var baseProbeInfo: ProbeInfo

    @OptIn(ExperimentalUnsignedTypes::class, DelicateCoroutinesApi::class)
    override fun onCreateViewModel() {
        super.onCreateViewModel()
        //当前选中的数据
        checkBleDevice = BleHelper.getConnectBleDevice()
        //当前连接的设备
        if (checkBleDevice == null && BleHelper.getBleBaseDevices().isNotEmpty()) {
            checkBleDevice = BleHelper.getBleBaseDevices()[0]
        }
        mBleListener = object : BleListener() {
            override fun onEnableDataNotify(type: UByte, json: String) {
                super.onEnableDataNotify(type, json)
                when (type) {
                    //获取探头信息
                    BleConstant.Cmd.GET_PROBE_INFO_RESPONSE -> {
                        //返回探头信息
                        val probeInfo = Gson().fromJson(json, ProbeInfo::class.java)
                        baseProbeInfo = probeInfo
                        //去获取读取采集信息
                        val uByteArray = probeInfo.mac.split(":").map { value -> value.toUByte(16) }
                            .toUByteArray()
                        val generateGetProbeInfoRequestData =
                            BleRequestData.generateReadSamplingInfoRequestData(
                                uByteArray,
                                baseProbeInfo.plusReadAllTestIndex(),
                            )
                        BleHelper.writeRetryWhen(
                            generateGetProbeInfoRequestData,
                            5,
                            object : BleWriteListener() {})
                    }

                    //返回探头采集信息
                    BleConstant.Cmd.READ_SAMPLING_INFO_RESPONSE -> {
                        val jsonObject = JSONObject(json)
                        val mac = jsonObject.optString("mac", "")
                        val samplingInfo = jsonObject.optString("samplingInfo", "")
                        val samplingInfoArray = Gson().fromJson<MutableList<ProbeTestingInfo>>(
                            samplingInfo,
                            object :
                                TypeToken<MutableList<ProbeTestingInfo>>() {}.type
                        )
                        baseProbeInfo.addListSamplingData(samplingInfoArray)
                        if (baseProbeInfo.isAllReaded()) {
                            probeInfoObservableField.postValue(baseProbeInfo)
                            return
                        }
                        //去获取读取采集信息
                        val uByteArray = mac.split(":").map { value -> value.toUByte(16) }
                            .toUByteArray()
                        val generateGetProbeInfoRequestData =
                            BleRequestData.generateReadSamplingInfoRequestData(
                                uByteArray,
                                baseProbeInfo.plusReadAllTestIndex()
                            )
                        BleHelper.writeRetryWhen(
                            generateGetProbeInfoRequestData,
                            5,
                            object : BleWriteListener() {})
                    }

                    //返回探头采集数据
                    BleConstant.Cmd.READ_SAMPLING_DATA_RESPONSE -> {
                        val jsonObject = JSONObject(json)
                        val mac = jsonObject.optString("mac", "")
                        if (TextUtils.equals(mac, currentTestingProbeAllInfo.mac)) {
                            val recordData = jsonObject.optString("recordData", "")
                            val probeSamplingRecordInfoList =
                                Gson().fromJson<MutableList<ProbeRecordEntity>>(
                                    recordData,
                                    object :
                                        TypeToken<MutableList<ProbeRecordEntity>>() {}.type
                                )
                            currentTestingProbeAllInfo.probeSamplingRecordInfoList.addAll(
                                probeSamplingRecordInfoList
                            )

                        }
                        //数据完成后刷新数据
                        currentTestingProbeAllInfo.plusRecordStartIndex()
                        if (currentTestingProbeAllInfo.isEndRead()) {
                            "currentTestingProbeAllInfo.isEndRead()=$currentTestingProbeAllInfo.isEndRead()".loge()
                            readProbeAllInfoEndList.add(currentTestingProbeAllInfo)

                            //====判断是否还有数据，如果没有说明读取完成====
                            val removeFirst = queueProbeAllInfo.removeFirstOrNull()
                            if (removeFirst == null) {
                                loadingChange.dismissDialog.postValue(false)
                                //====打印读取完成的数据====
                                readProbeAllInfoEndList.forEach {
                                    "mac地址：${it.mac}".loge()
                                    "采集记录数量：${it.recordNum}".loge()
                                    "读取采集数量：${it.probeSamplingRecordInfoList.size}".loge()
                                }

                                keepDataToSql()
                                return
                            }
                            //====继续采取下一个====
                            currentTestingProbeAllInfo = removeFirst
                        }
                        //====继续发送下一个命令====
                        val macUByteArray = currentTestingProbeAllInfo.mac.split(":")
                            .map { value -> value.toUByte(16) }
                            .toUByteArray()
                        val generateReadSamplingDataRequestData =
                            BleRequestData.generateReadSamplingDataRequestData(
                                macUByteArray,
                                currentTestingProbeAllInfo.getRecordStartIndexNum(),
                                currentTestingProbeAllInfo.getSingleRecordCallBackSize()
                            )
                        BleHelper.writeRetryWhen(
                            generateReadSamplingDataRequestData,
                            10,
                            object : BleWriteListener() {})
                    }
                }
            }
        }

        //====设置数据监听====
        mBleListener?.let {
            BleHelper.addBleListener(it)
        }
    }

    override fun onDestroyViewModel() {
        super.onDestroyViewModel()
        mBleListener?.let {
            BleHelper.removeBleListener(it)
        }
    }

    fun checkReadData(map: MutableMap<String, String>) {
        if (map.isEmpty()) {
            toast("请选择要上传的记录")
            return
        }
        val list = baseProbeInfo.getList()
        queueProbeAllInfo.clear()
        list.forEach {
            if (map.containsKey(it.recordStartTime)) {
//                val collectionRecord =
//                    DbHelper.init().getCollectionDao()
//                        .getCollectionRecord(
//                            baseProbeInfo.mac,
//                            it.recordStartTime
//                        )
//                if (collectionRecord != null) {
//                    toast("选中中存在已上传采集记录")
//                    return
//                }
                val probeInfo = ProbeAllInfo(
                    baseProbeInfo.mac,
                    baseProbeInfo.sw,
                    baseProbeInfo.hw,
                    baseProbeInfo.battery,
                    baseProbeInfo.feature,
                    baseProbeInfo.wayNum,
                    baseProbeInfo.wayIndex,
                    it.recordSamplingInterval,
                    it.recordStartTime,
                    baseProbeInfo.model,
                    it.recordNum
                )
                queueProbeAllInfo.add(probeInfo)
            }
        }
        //开始采集
        loadingChange.showDialog.postValue("开始读取采集数据...")
        currentTestingProbeAllInfo = queueProbeAllInfo.removeFirst()
        //轮训检测是否超时没返回
        val macUByteArray =
            currentTestingProbeAllInfo.mac.split(":").map { value -> value.toUByte(16) }
                .toUByteArray()
        val generateReadSamplingDataRequestData =
            BleRequestData.generateReadSamplingDataRequestData(
                macUByteArray,
                currentTestingProbeAllInfo.getRecordStartIndexNum(),
                currentTestingProbeAllInfo.getSingleRecordCallBackSize()
            )
        BleHelper.writeRetryWhen(generateReadSamplingDataRequestData,10,object :BleWriteListener(){})
//        CoroutineScope(Dispatchers.IO).launch {
//            baseContext.value?.let {
//                val collectionRecord = DbHelper.init().getCollectionDao().getCollectionRecord(
//                    currentTestingProbeAllInfo.mac,
//                    currentTestingProbeAllInfo.recordStartTime
//                )
//                if (collectionRecord != null) {
//                    ExcelUtil.exportExcel(
//                        it,
//                        collectionRecord
//                    )
//                }
//            }
//        }
    }

    @OptIn(ExperimentalUnsignedTypes::class)
    fun readOnePiece() {
        if (readCollectionBtn.get()) {
            val bean = EventMessage(EventType.SWITCH_MAIN_PAGE, "")
            bean.arg1 = "3"
            EventBus.getDefault().post(bean)
            finish()
            return
        }
        queueProbeAllInfo.clear()
        val list = baseProbeInfo.getList()
        if (list.isEmpty()) {
            toast("未有采集数据")
            return
        }
        list.forEach {
//            val collectionRecord =
//                DbHelper.init().getCollectionDao()
//                    .getCollectionRecord(
//                        baseProbeInfo.mac,
//                        it.recordStartTime
//                    )
//            if (collectionRecord!=null){
//                toast("选中中存在已上传采集记录")
//                return
//            }
            val probeInfo = ProbeAllInfo(
                baseProbeInfo.mac,
                baseProbeInfo.sw,
                baseProbeInfo.hw,
                baseProbeInfo.battery,
                baseProbeInfo.feature,
                baseProbeInfo.wayNum,
                baseProbeInfo.wayIndex,
                it.recordSamplingInterval,
                it.recordStartTime,
                baseProbeInfo.model,
                it.recordNum
            )
            queueProbeAllInfo.add(probeInfo)
        }
        //开始采集
        loadingChange.showDialog.postValue("开始读取采集数据...")
        currentTestingProbeAllInfo = queueProbeAllInfo.removeFirst()
        //轮训检测是否超时没返回
        val macUByteArray =
            currentTestingProbeAllInfo.mac.split(":").map { value -> value.toUByte(16) }
                .toUByteArray()
        val generateReadSamplingDataRequestData =
            BleRequestData.generateReadSamplingDataRequestData(
                macUByteArray,
                currentTestingProbeAllInfo.getRecordStartIndexNum(),
                currentTestingProbeAllInfo.getSingleRecordCallBackSize()
            )
        BleHelper.writeRetryWhen(
            generateReadSamplingDataRequestData,
            10,
            object : BleWriteListener() {})
    }

    fun deleteAllTestingData() {
        val macDeleteUByteArray =
            baseProbeInfo.mac.split(":")
                .map { value -> value.toUByte(16) }
                .toUByteArray()
        val generateClearProbeSamplingDataRequestData =
            BleRequestData.generateClearProbeSamplingDataRequestData(macDeleteUByteArray)
        BleHelper.writeDelay(100, generateClearProbeSamplingDataRequestData)
        toast("清除完成")
        finish()
    }

    fun initProbeInfo(probeInfo: ProbeInfo?) {
        probeInfo?.let {
            probeInfoObservableField.postValue(it)
            val macUByteArray = it.mac.split(":")
                .map { value -> value.toUByte(16) }
                .toUByteArray()
            val generateReadSamplingDataRequestData =
                BleRequestData.generateGetProbeInfoRequestData(
                    macUByteArray
                )
            BleHelper.writeRetryWhen(
                generateReadSamplingDataRequestData,
                5,
                object : BleWriteListener() {

                })
        }
    }

    fun uploadProbeCollection(collectionEntity: CollectionEntity) {
        //离线不做上传
        if (UserCacheHelper.isOffline()) {
            return
        }
        baseContext.value?.let { that ->
            request({
                HttpRequestCoroutine.uploadProbeCollection(
                    that, collectionEntity
                )
            }, {
                val nextCollectionEntity = queueCollectionEntity.removeFirstOrNull()
                if (nextCollectionEntity == null) {
                    loadingChange.dismissDialog.postValue(false)
                    val bean = EventMessage(EventType.SWITCH_MAIN_PAGE, "")
                    bean.arg1 = "3"
                    EventBus.getDefault().post(bean)
                    finish()
                } else {
                    uploadProbeCollection(nextCollectionEntity)
                }
                "上传成功".loge()
            }, {
                val nextCollectionEntity = queueCollectionEntity.removeFirstOrNull()
                if (nextCollectionEntity == null) {
                    loadingChange.dismissDialog.postValue(false)
                    val bean = EventMessage(EventType.SWITCH_MAIN_PAGE, "")
                    bean.arg1 = "3"
                    EventBus.getDefault().post(bean)
                    finish()
                } else {
                    uploadProbeCollection(nextCollectionEntity)
                }
                "上传失败".loge()
            })
        }
    }

    //保存到数据数据库
    fun keepDataToSql() {
        baseContext.value?.let { that ->
            //探头温度和气压数据
            readProbeAllInfoEndList.forEach {
                it.probeSamplingRecordInfoList.map { item ->
                    item.mac = it.mac
                    item.recordStartTime = it.recordStartTime
                    item.recordSamplingInterval = it.recordSamplingInterval
                    item.wayNum = it.wayNum
                    item.wayIndex = it.wayIndex
                    val scaleNumber = BigDecimal(item.temperature / 100)
                    item.temperature = scaleNumber.setScale(2, RoundingMode.HALF_UP).toDouble()
                }
                //先存记录
                DbHelper.init().getProbeRecordDao().insertAll(it.probeSamplingRecordInfoList)
                val collectionEntity = CollectionEntity(
                    it.mac,
                    it.sw,
                    it.hw,
                    it.battery,
                    it.feature,
                    it.wayNum,
                    it.wayIndex,
                    it.recordSamplingInterval,
                    it.recordStartTime,
                    it.model,
                    it.recordNum
                )
                DbHelper.init().getCollectionDao().insert(collectionEntity)
                queueCollectionEntity.add(collectionEntity)
            }
            //一个一个传
            uploadProbeCollection(queueCollectionEntity.removeFirst())
        }
    }
}